package com.ly.heart.service.king;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.gson.Gson;
import com.kingdee.bos.webapi.entity.IdentifyInfo;
import com.kingdee.bos.webapi.entity.RepoRet;
import com.kingdee.bos.webapi.sdk.K3CloudApi;
import com.ly.common.exception.CustomException;
import com.ly.common.utils.erp.CommonUtil;
import com.ly.common.utils.erp.KingConstUtil;
import com.ly.heart.domain.KingFinanceReceiptRefundDetailEntity;
import com.ly.heart.domain.KingFinanceReceiptRefundEntity;
import com.ly.heart.domain.KingOrgEntity;
import com.ly.heart.domain.king.BaseChildBo;
import com.ly.heart.domain.king.refund.ReceiptRefundBo;
import com.ly.heart.domain.king.refund.ReceiptRefundDetailBo;
import com.ly.heart.domain.request.KingBaseSingleRequest;
import com.ly.heart.domain.response.KingBaseResponse;
import com.ly.heart.domain.response.KingBaseResponseError;
import com.ly.heart.domain.response.KingBaseResponseSuccessEntity;
import com.ly.heart.service.IKingFinanceReceiptRefundDetailService;
import com.ly.heart.service.IKingFinanceReceiptRefundService;
import com.ly.heart.service.IKingOrgService;
import com.ly.heart.util.CurrentUserUtil;
import com.ly.heart.util.KingCommonUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author: Wuzh
 * @Description:收款退款单推送金蝶业务
 * @Date Created in 22:46 2024-09-09
 * @return
 */

@Component
@Slf4j
public class ReceiptRefundPushService {


    @Resource
    private IKingFinanceReceiptRefundService iKingFinanceReceiptRefundService;
    @Resource
    private IKingFinanceReceiptRefundDetailService iKingFinanceReceiptRefundDetailService;
    @Resource
    private IKingOrgService iKingOrgService;

    public void push (String id) {
        KingOrgEntity orgEntity = iKingOrgService.getOne ( new LambdaQueryWrapper<KingOrgEntity> ().eq ( KingOrgEntity :: getOrgId, CurrentUserUtil.getCompanyId () ).eq ( KingOrgEntity :: getIsDisabled, true ) );
        if ( orgEntity == null ) {
            throw new CustomException ( "请先至系统管理中配置金蝶账套！" );
        }
        IdentifyInfo identifyInfo = KingCommonUtil.getIdentifyInfo ( orgEntity );
        K3CloudApi client = new K3CloudApi ( identifyInfo );
        log.info ( "收款退款单调用金蝶下推->{}", id );
        KingFinanceReceiptRefundEntity kingFinanceReceiptRefundEntity = iKingFinanceReceiptRefundService.querySingleById ( id );
        if ( kingFinanceReceiptRefundEntity == null ) {
            throw new CustomException ( "无此收款退款单！" );
        }
        if ( kingFinanceReceiptRefundEntity.getIsSend () == KingConstUtil.KING_DATA_IS_SEND_YES ) {
            throw new CustomException ( "该单据已推送金蝶，无需重复推送！" );
        }
        ReceiptRefundBo bo = assembleReceipt ( kingFinanceReceiptRefundEntity );
        try {
            save ( bo, client );
            submit ( bo, client );
            audit ( bo, client );
            updateSendSuccess ( kingFinanceReceiptRefundEntity.getId () );
        } catch ( Exception e ) {
            e.printStackTrace ();
            throw new CustomException ( "推送金额失败，请稍后重试！" );
        }
    }

    private void save (ReceiptRefundBo bo, K3CloudApi client) throws Exception {
        KingBaseSingleRequest singleRequest = new KingBaseSingleRequest ();
        singleRequest.setModel ( bo );
        String s = JSONObject.toJSONString ( singleRequest );
        log.info ( "收款退款单转JSON->{}", s );
        String resultJson = client.save ( KingConstUtil.AR_REFUNDBILL, s );
        Gson gson = new Gson ();
        //对返回结果进行解析和校验
        RepoRet repoRet = gson.fromJson ( resultJson, RepoRet.class );
        KingBaseResponse baseResponse = JSONObject.parseObject ( gson.toJson ( repoRet.getResult ().getResponseStatus () ), KingBaseResponse.class );
        StringBuilder sb = new StringBuilder ();
        if ( baseResponse.getIsSuccess () ) {
            List<KingBaseResponseSuccessEntity> successEntities = baseResponse.getSuccessEntitys ();
            sb.append ( "收款退款单-编码为：【" );
            successEntities.forEach ( success -> {
                sb.append ( success.getNumber () ).append ( ";" );
            } );
            sb.append ( "】" );
            log.info ( "{} 推送成功", sb );

        } else {
            List<KingBaseResponseError> errors = baseResponse.getErrors ();
            errors.forEach ( err -> {
                sb.append ( err.getMessage () ).append ( ";" );
            } );
            throw new RuntimeException ( "收款退款单-推送失败：【" + sb + "】" );
        }
    }

    private void submit (ReceiptRefundBo bo, K3CloudApi client) throws Exception {
        List<String> strings = new ArrayList<> ();
        strings.add ( bo.getFBillNo () );
        bo.setNumbers ( strings );
        String jsonData = JSON.toJSONString ( bo );
        String resultJson = client.submit ( KingConstUtil.AR_REFUNDBILL, jsonData );
        Gson gson = new Gson ();
        //对返回结果进行解析和校验
        RepoRet repoRet = gson.fromJson ( resultJson, RepoRet.class );
        KingBaseResponse baseResponse = JSONObject.parseObject ( gson.toJson ( repoRet.getResult ().getResponseStatus () ), KingBaseResponse.class );
        StringBuilder sb = new StringBuilder ();
        if ( baseResponse.getIsSuccess () ) {
            //提交成功
            List<KingBaseResponseSuccessEntity> successEntities = baseResponse.getSuccessEntitys ();
            sb.append ( "收款退款单-编码为：【" );
            successEntities.forEach ( success -> {
                sb.append ( success.getNumber () ).append ( ";" );
            } );
            sb.append ( "】" );
            log.error ( "{} 提交成功", sb );
        } else {
            List<KingBaseResponseError> errors = baseResponse.getErrors ();
            errors.forEach ( err -> {
                sb.append ( err.getMessage () ).append ( ";" );
            } );
            throw new RuntimeException ( "收款退款单提交失败：【" + sb + "】" );
        }
    }

    private void audit (ReceiptRefundBo bo, K3CloudApi client) throws Exception {
        List<String> strings = new ArrayList<> ();
        strings.add ( bo.getFBillNo () );
        bo.setNumbers ( strings );
        String jsonData = JSON.toJSONString ( bo );
        String resultJson = client.audit ( KingConstUtil.AR_REFUNDBILL, jsonData );
        Gson gson = new Gson ();
        //对返回结果进行解析和校验
        RepoRet repoRet = gson.fromJson ( resultJson, RepoRet.class );
        KingBaseResponse baseResponse = JSONObject.parseObject ( gson.toJson ( repoRet.getResult ().getResponseStatus () ), KingBaseResponse.class );
        StringBuilder sb = new StringBuilder ();
        if ( baseResponse.getIsSuccess () ) {
            //提交成功
            List<KingBaseResponseSuccessEntity> successEntities = baseResponse.getSuccessEntitys ();
            sb.append ( "收款退款单-编码为：【" );
            successEntities.forEach ( success -> {
                sb.append ( success.getNumber () ).append ( ";" );
            } );
            sb.append ( "】" );
            log.error ( "{} 审核成功", sb );
        } else {
            List<KingBaseResponseError> errors = baseResponse.getErrors ();
            errors.forEach ( err -> {
                sb.append ( err.getMessage () ).append ( ";" );
            } );
            throw new RuntimeException ( "收款退款单审核失败：【" + sb + "】" );
        }
    }

    private void updateSendSuccess (String id) {
        KingFinanceReceiptRefundEntity receiptRefundEntity = new KingFinanceReceiptRefundEntity ();
        receiptRefundEntity.setId ( id );
        receiptRefundEntity.setIsSend ( KingConstUtil.KING_DATA_IS_SEND_YES );
        boolean b = iKingFinanceReceiptRefundService.updateById ( receiptRefundEntity );
        if ( ! b ) {
            throw new CustomException ( "修改推送金额状态失败！" );
        }
    }


    private ReceiptRefundBo assembleReceipt (KingFinanceReceiptRefundEntity kingFinanceReceiptRefundEntity) {
        ReceiptRefundBo bo = new ReceiptRefundBo ();
        //1.基础
        bo.setFBillNo ( kingFinanceReceiptRefundEntity.getDocNo () );
        //单据类型
        BaseChildBo docType = new BaseChildBo ().setFNumber ( kingFinanceReceiptRefundEntity.getDocTypeCode () );
        bo.setFBillTypeID ( docType );
        //收款单位类型
        bo.setFRECTUNITTYPE ( kingFinanceReceiptRefundEntity.getReceiptDeptType () );
        //付款组织
        BaseChildBo payOrg = new BaseChildBo ().setFNumber ( /*kingFinanceReceiptRefundEntity.getPayCompanyCode ()*/ "100" );
        bo.setFPAYORGID ( payOrg );
        //收款单位
        BaseChildBo receiptDept = new BaseChildBo ().setFNumber ( kingFinanceReceiptRefundEntity.getReceiptDeptCode () );
        bo.setFRECTUNIT ( receiptDept );
        //结算组织
        BaseChildBo settOrg = new BaseChildBo ().setFNumber ( /*kingFinanceReceiptRefundEntity.getSettlementCompanyCode ()*/ "100" );
        bo.setFSETTLEORGID ( settOrg );
        //业务日期
        bo.setFDATE ( CommonUtil.getDateStrFormat ( kingFinanceReceiptRefundEntity.getBusinessTime (), "yyyy-MM-dd" ) );
        //币别
        BaseChildBo currency = new BaseChildBo ().setFNumber ( kingFinanceReceiptRefundEntity.getCurrencyCode () );
        bo.setFCURRENCYID ( currency );

        //销售组织，组织字段需要从金蝶重新拉取
        BaseChildBo saleOrg = new BaseChildBo ().setFNumber ( /*kingFinanceReceiptRefundEntity.getSaleCompanyCode ()*/ "100" );
        bo.setFSALEORGID ( saleOrg );

        //往来单位类型
        bo.setFCONTACTUNITTYPE ( kingFinanceReceiptRefundEntity.getTransactionCompanyType () );
        //应退金额
        bo.setFREFUNDTOTALAMOUNTFOR ( kingFinanceReceiptRefundEntity.getCopeRefundMoney () );

        //销售部门
        BaseChildBo saleDept = new BaseChildBo ().setFNumber ( kingFinanceReceiptRefundEntity.getSaleDeptCode () );
        bo.setFSALEDEPTID ( saleDept );

        //往来单位
        BaseChildBo tracDept = new BaseChildBo ().setFNumber ( kingFinanceReceiptRefundEntity.getTransactionCompanyCode () );
        bo.setFCONTACTUNIT ( tracDept );
        //实退金额
        bo.setFREALREFUNDAMOUNTFOR ( kingFinanceReceiptRefundEntity.getActualRefundMoney () );
        //期望付款日期
        bo.setFBookingDate ( CommonUtil.getDateStrFormat ( kingFinanceReceiptRefundEntity.getExpectedPayTime (), "yyyy-MM-dd" ) );
        //备注
        bo.setFREMARK ( kingFinanceReceiptRefundEntity.getRemarks () );
        //销售员
        BaseChildBo saleUser = new BaseChildBo ().setFNumber ( kingFinanceReceiptRefundEntity.getSaleUserCode () );
        bo.setFSALEERID ( saleUser );
        BaseChildBo settCurrency = new BaseChildBo ().setFNumber ( kingFinanceReceiptRefundEntity.getSettlementCurrencyCode () );
        bo.setFSETTLECUR ( settCurrency );
        //应退金额本位币
        bo.setFREFUNDTOTALAMOUNT ( kingFinanceReceiptRefundEntity.getCopeRefundMoneyCurrency () );
        //退款金额本位币
        bo.setFREFUNDAMOUNT_H ( kingFinanceReceiptRefundEntity.getRefundMoneyCurrency () );
        //实退金额本位币
        bo.setFREALREFUNDAMOUNT ( kingFinanceReceiptRefundEntity.getActualRefundMoneyCurrency () );
        //结算本位币
        //BaseChildBo settCurrencyOwn = new BaseChildBo ().setFNumber ( kingFinanceReceiptRefundEntity.getSettlementCurrencyCode () );
        //bo.setFSETTLEMAINBOOKID ( settCurrencyOwn );
        //明细行列表
        bo.setFREFUNDBILLENTRY ( assembleReceiptDetailBo ( kingFinanceReceiptRefundEntity.getId () ) );
        return bo;
    }

    private List<ReceiptRefundDetailBo> assembleReceiptDetailBo (String receiptRefundId) {
        List<ReceiptRefundDetailBo> bos = new ArrayList<> ();
        List<KingFinanceReceiptRefundDetailEntity> list = iKingFinanceReceiptRefundDetailService.list ( new LambdaQueryWrapper<KingFinanceReceiptRefundDetailEntity> ().
                eq ( KingFinanceReceiptRefundDetailEntity :: getReceiptRefundId, receiptRefundId ) );
        list.forEach ( detail -> {
            ReceiptRefundDetailBo bo = new ReceiptRefundDetailBo ();
            //结算方式
            BaseChildBo settType = new BaseChildBo ().setFNumber ( detail.getKingSettlementTypeCode () );
            bo.setFSETTLETYPEID ( settType );
            //原收款用途
            BaseChildBo purpost = new BaseChildBo ().setFNumber ( detail.getReceiptPurposeCode () );
            bo.setFPURPOSEID ( purpost );
            //实退金额
            //bo.setFREALREFUNDAMOUNTFOR_D ( detail.getActualRefundMoney () );
            //应退金额
            bo.setFREFUNDAMOUNTFOR ( detail.getCopeRefundMoney () );
            //退款金额=应退金额
            bo.setFREFUNDAMOUNTFOR_E ( detail.getCopeRefundMoney () );
            //销售订单号
            bo.setFREFUNDAMOUNTFOR ( detail.getSaleNo () );
            //现金折扣
            bo.setFDISTAMOUNTFOR ( detail.getCashDiscount () );
            //长短款
            bo.setFOUAMOUNTFOR ( detail.getLongShortPay () );
            //手续费
            bo.setFHANDLINGCHARGEFOR ( detail.getHandlingFees () );
            //我方银行账号
            BaseChildBo account = new BaseChildBo ().setFNumber ( detail.getBankNumber () ); ////?
            bo.setFACCOUNTID ( account );
            //现金账号
            //BaseChildBo cashAccount = new BaseChildBo ().setFNumber ( detail.getBankNumber () ); ////?
            //bo.setFCashAccount ( cashAccount );

            //结算号
            bo.setFSETTLENO ( detail.getSettlementNumber () );
            //备注
            bo.setFNOTE ( detail.getRemarks () );
            //银行处理状态
            bo.setFBankStatus ( detail.getBackProcessingStatus () );
            //提交银行状态
            bo.setFSubmitStatus ( detail.getSubmitBankStatus () );
            //物料编码
            BaseChildBo material = new BaseChildBo ().setFNumber ( detail.getMaterialCode () );
            bo.setFMATERIALID ( material );
            //含税单价
            bo.setFPrice ( detail.getTaxPrice () );
            //数量
            bo.setFQty ( detail.getNum () );
            //订单行号
            bo.setFMATERIALSEQ ( detail.getSaleLineNumber () );
            //费用项目
            BaseChildBo fcost = new BaseChildBo ().setFNumber ( detail.getFeeCode () );
            bo.setFCOSTID ( fcost );
            //费用项目
            BaseChildBo fdept = new BaseChildBo ().setFNumber ( detail.getFeeBearDeptCode () );
            bo.setFCOSTDEPARTMENTID ( fdept );
            bos.add ( bo );
        } );
        return bos;
    }

}
